gtkmain: Add API to get the target of a GdkEvent
authorCarlos Garnacho <carlosg@gnome.org>
Thu, 4 May 2017 11:49:34 +0000 (13:49 +0200)
committerCarlos Garnacho <carlosg@gnome.org>
Thu, 25 May 2017 14:25:59 +0000 (16:25 +0200)
This can be used on grabbing situations to determine the target of
the event. This mainly matters for GtkMenu.

gtk/gtkmain.c
gtk/gtkmain.h

index 910ff0e9fb475a44f7b5ea547c4fe8aef2f25e62..33429accf756bffd301d1cac218e715bd7aa1664 100644 (file)
@@ -1329,6 +1329,7 @@ synth_crossing_for_motion (GtkWidget     *widget,
   gdouble x, y;
 
   event = gdk_event_new (enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY);
+  gdk_event_set_user_data (event, G_OBJECT (widget));
   gdk_event_set_device (event, gdk_event_get_device (source));
   gdk_event_set_source_device (event, gdk_event_get_source_device (source));
 
@@ -1678,6 +1679,8 @@ gtk_main_do_event (GdkEvent *event)
   if (check_event_in_child_popover (event_widget, grab_widget))
     grab_widget = event_widget;
 
+  gdk_event_set_user_data (event, G_OBJECT (event_widget));
+
   /* If the widget receiving events is actually blocked by another
    * device GTK+ grab
    */
@@ -2361,6 +2364,50 @@ gtk_get_event_widget (GdkEvent *event)
   return widget;
 }
 
+/**
+ * gtk_get_event_target:
+ * @event: a #GdkEvent
+ *
+ * If @event is %NULL or the event was not associated with any widget,
+ * returns %NULL, otherwise returns the widget that is the deepmost
+ * receiver of the event.
+ *
+ * Returns: (transfer none) (nullable): the target widget, or %NULL
+ *
+ * Since: 3.90
+ */
+GtkWidget *
+gtk_get_event_target (GdkEvent *event)
+{
+  return GTK_WIDGET (gdk_event_get_user_data (event));
+}
+
+/**
+ * gtk_get_event_target_with_type:
+ * @event: a #GdkEvent
+ *
+ * If @event is %NULL or the event was not associated with any widget,
+ * returns %NULL, otherwise returns first widget found from the event
+ * target to the toplevel that matches @type.
+ *
+ * Returns: (transfer none) (nullable): the widget in the target stack
+ * with the given type, or %NULL
+ *
+ * Since: 3.90
+ */
+GtkWidget *
+gtk_get_event_target_with_type (GdkEvent *event,
+                                GType     type)
+{
+  GtkWidget *target;
+
+  target = gtk_get_event_target (event);
+  while (target && !g_type_is_a (G_OBJECT_TYPE (target), type))
+    target = gtk_widget_get_parent (target);
+
+  return target;
+}
+
 static gboolean
 propagate_event_up (GtkWidget *widget,
                     GdkEvent  *event,
index 49e19c9f224ae689100be5de1edd3d113e25f865..47681bee1ae6648cc036571cc9f1b95b62be6fd3 100644 (file)
@@ -151,6 +151,13 @@ GdkDevice *gtk_get_current_event_device (void);
 GDK_AVAILABLE_IN_ALL
 GtkWidget *gtk_get_event_widget         (GdkEvent        *event);
 
+GDK_AVAILABLE_IN_3_90
+GtkWidget *gtk_get_event_target         (GdkEvent        *event);
+
+GDK_AVAILABLE_IN_3_90
+GtkWidget *gtk_get_event_target_with_type (GdkEvent *event,
+                                           GType     type);
+
 GDK_AVAILABLE_IN_ALL
 void       gtk_propagate_event          (GtkWidget       *widget,
                                          GdkEvent        *event);